use crypto::blockmodes::PkcsPadding;
use crypto::aes::{ecb_decryptor,ecb_encryptor,cbc_decryptor,cbc_encryptor,KeySize};
use rand::rngs::OsRng;
use rand::RngCore;
use base64::DecodeError;
use crypto::buffer::{ ReadBuffer, WriteBuffer, BufferResult ,RefReadBuffer,RefWriteBuffer};
use crypto::symmetriccipher::SymmetricCipherError;

pub fn base64_encode(buf:&[u8])->String{
    base64::encode(buf)
}

pub fn base64_decode(buf:&[u8])->Result<Vec<u8>, DecodeError>{
    base64::decode(buf)
}

//生成指定长度的随机数
pub fn rang_bytes(len:usize)->Vec<u8>{
    let mut buf = vec![0_u8; len];
    let mut rng = OsRng::default();
    rng.fill_bytes(buf.as_mut_slice());
    buf
}

//默认是128
pub fn aes_cbc_encode(size:&str,key:&[u8],iv:&[u8],src:&[u8])->Result<Vec<u8>,String>{
    let ks = match size {
        "192"=> KeySize::KeySize192,
        "256"=> KeySize::KeySize256,
        _=>KeySize::KeySize128
    };
    let mut encrptor = cbc_encryptor(ks, key, iv, PkcsPadding);
    let mut des = Vec::<u8>::new();
    let mut input = RefReadBuffer::new(src);
    let mut buffer = [0; 4096];
    let mut output = RefWriteBuffer::new(&mut buffer);
    loop {
        let result = match encrptor.encrypt(&mut input, &mut output, true){
            Ok(o)=>o,
            Err(e)=> {
                match e {
                    SymmetricCipherError::InvalidLength=>return Err("InvalidLength".to_string()),
                    SymmetricCipherError::InvalidPadding=>return Err("InvalidPadding".to_string()),
                }
            }
        };
        des.extend(output.take_read_buffer().take_remaining().iter().map(|&i| i));
        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }
    Ok(des)
}

pub fn aes_cbc_decode(size:&str,key:&[u8],iv:&[u8],src:&[u8])->Result<Vec<u8>,String>{
    let ks = match size {
        "192"=> KeySize::KeySize192,
        "256"=> KeySize::KeySize256,
        _=>KeySize::KeySize128
    };
    let mut decrptor = cbc_decryptor(ks, key, iv, PkcsPadding);
    let mut des = Vec::<u8>::new();
    let mut input = RefReadBuffer::new(src);
    let mut buffer = [0; 4096];
    let mut output = RefWriteBuffer::new(&mut buffer);
    loop {
        let result = match decrptor.decrypt(&mut input, &mut output, true){
            Ok(o)=>o,
            Err(e)=> {
                match e {
                    SymmetricCipherError::InvalidLength=>return Err("InvalidLength".to_string()),
                    SymmetricCipherError::InvalidPadding=>return Err("InvalidPadding".to_string()),
                }
            }
        };
        des.extend(output.take_read_buffer().take_remaining().iter().map(|&i| i));
        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }
    Ok(des)
}

pub fn aes_ecb_encode(size:&str,key:&[u8],src:&[u8])->Result<Vec<u8>,String>{
    let ks = key_size_from_str(size);
    let mut encryptor = ecb_encryptor(ks, key, PkcsPadding);
    let mut des = Vec::<u8>::new();
    let mut input = RefReadBuffer::new(src);
    let mut buffer = [0_u8;4096];
    let mut output = RefWriteBuffer::new(&mut buffer[..]);
    loop {
        let res = encryptor.encrypt(&mut input,&mut output,true);
        let buf_res = match res {
            Ok(o)=>o,
            Err(e)=>{
                match e {
                    SymmetricCipherError::InvalidLength=>return Err(String::from("InvalidLength")),
                    SymmetricCipherError::InvalidPadding=>return Err(String::from("InvalidPadding")),
                }
            }
        };
        des.extend(output.take_read_buffer().take_remaining().iter().map(|&i| i));
        match buf_res {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }
    return Ok(des)
}

pub fn aes_ecb_decode(size:&str,key:&[u8],src:&[u8])->Result<Vec<u8>,String>{
    let ks = key_size_from_str(size);
    let mut decryptor = ecb_decryptor(ks, key, PkcsPadding);
    let mut des = Vec::<u8>::new();
    let mut input = RefReadBuffer::new(src);
    let mut buffer = [0_u8;4096];
    let mut output = RefWriteBuffer::new(&mut buffer[..]);
    loop {
        let res = decryptor.decrypt(&mut input,&mut output,true);
        let buf_res = match res {
            Ok(o)=>o,
            Err(e)=>{
                match e {
                    SymmetricCipherError::InvalidLength=>return Err(String::from("InvalidLength")),
                    SymmetricCipherError::InvalidPadding=>return Err(String::from("InvalidPadding")),
                }
            }
        };
        des.extend(output.take_read_buffer().take_remaining().iter().map(|&i| i));
        match buf_res {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }
    return Ok(des)
}

fn key_size_from_str(key:&str)->KeySize{
    match key {
        "192"=> KeySize::KeySize192,
        "256"=> KeySize::KeySize256,
        _=>KeySize::KeySize128
    }
}